package services

import (
	"fmt"
	"gitee.com/captials-team/ubdframe/src/domain/dto"
	"gitee.com/captials-team/ubdframe/src/domain/dto/paginate"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/domain/models"
	"gitee.com/captials-team/ubdframe/src/infrastructure/caches"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"go.uber.org/dig"
	"strings"
)

type TelemetryService struct {
	l           v1log.ILog
	metaDao     interfaces.ItfMetricMetaDao       //测点元数据dao
	dataDao     interfaces.ItfMetricDataDao       //历史数据dao
	latestDao   interfaces.ItfMetricLatestDataDao //最新数据dao
	statDao     interfaces.ItfMetricStatDataDao   //统计数据dao
	cacheByName *caches.CacheFacade[string, string]
}

func NewTelemetryService(di *dig.Container, l v1log.ILog,
	metaDao interfaces.ItfMetricMetaDao,
	dataDao interfaces.ItfMetricDataDao,
	latestDao interfaces.ItfMetricLatestDataDao,
	statDao interfaces.ItfMetricStatDataDao,
	cache caches.ItfCache) *TelemetryService {
	ctr := &TelemetryService{
		l:           l,
		metaDao:     metaDao,
		dataDao:     dataDao,
		latestDao:   latestDao,
		statDao:     statDao,
		cacheByName: caches.NewCacheFacade[string, string](cache),
	}
	//设置分表策略
	if d, ok := dataDao.(interfaces.ItfSubTableStrategy); ok {
		l.Info("metricData set subTable strategy")
		d.SetSplitStrategyById(metaDao.SubTableStrategy())
	}
	if d, ok := latestDao.(interfaces.ItfSubTableStrategy); ok {
		l.Info("metricLatest set subTable strategy")
		d.SetSplitStrategyById(metaDao.SubTableStrategy())
	}
	if d, ok := statDao.(interfaces.ItfSubTableStrategy); ok {
		l.Info("metricStat set subTable strategy")
		d.SetSplitStrategyById(metaDao.SubTableStrategy())
	}

	return ctr
}

// CheckCreateMetric 检查并创建测点
func (s *TelemetryService) CheckCreateMetric(add *models.Metrics) (int64, error) {
	find, err := s.metaDao.QueryByName(add.Name)
	if err != nil {
		return 0, err
	}
	//已存在则不处理
	if find != nil {
		add.Id = find.Id
		add.SplitKey = find.SplitKey
		add.Extends = find.Extends
		return find.Id, nil
	}
	//不存在则创建
	_, err = s.metaDao.Add(add)
	if err != nil {
		return 0, err
	}

	//初始化表
	if add.SplitKey != "" {
		err = s.dataDao.InitSplitTable(add.SplitKey)
		if err != nil {
			return 0, err
		}
		err = s.statDao.InitSplitTable(add.SplitKey)
		if err != nil {
			return 0, err
		}
	}
	return add.Id, nil
}

// CreateMetric 创建测点
func (s *TelemetryService) CreateMetric(add *models.Metrics) (int64, error) {
	//不存在则创建
	_, err := s.metaDao.Add(add)
	if err != nil {
		return 0, err
	}

	//初始化表
	if add.SplitKey != "" {
		err = s.dataDao.InitSplitTable(add.SplitKey)
		if err != nil {
			return 0, err
		}
		err = s.statDao.InitSplitTable(add.SplitKey)
		if err != nil {
			return 0, err
		}
	}
	return add.Id, nil
}

// QueryMetric 查询某个测点信息
func (s *TelemetryService) QueryMetric(metricId int64) (*models.Metrics, error) {
	return s.metaDao.Query(metricId)
}

// QueryMetricByName 查询某个测点信息
func (s *TelemetryService) QueryMetricByName(name string) (*models.Metrics, error) {
	return s.metaDao.QueryByName(name)
}

func (s *TelemetryService) QueryLatestData(metricId int64) (*models.MetricData, error) {
	return s.latestDao.Query(metricId)
}

// getSplitTableKey 获取分表key
func (s *TelemetryService) getSplitTableKey(metricId int64) (string, error) {
	f := s.metaDao.SubTableStrategy()
	return f(metricId), nil
}

// SearchHistoryData 历史测点数据
func (s *TelemetryService) SearchHistoryData(req *dto.SearchMetricDataDto, pa *paginate.Pager) ([]*models.MetricData, *paginate.Pager, error) {
	if req.MetricId == 0 {
		return nil, nil, fmt.Errorf("must be metric id")
	}
	var err error
	if err != nil {
		return nil, nil, err
	}
	return s.dataDao.Search(req, pa)
}

// QuerySumData 获取历史测点数据sum数据
func (s *TelemetryService) QuerySumData(req *dto.SearchMetricDataDto) (*models.MetricValueData, error) {
	return s.dataDao.QuerySum(req)
}

// SearchStatData 测点数据列表
func (s *TelemetryService) SearchStatData(req *dto.SearchMetricStatDto, pa *paginate.Pager) ([]*models.MetricStatValueData, *paginate.Pager, error) {
	if req.MetricId == 0 {
		return nil, nil, fmt.Errorf("must be metric id")
	}
	var err error
	if err != nil {
		return nil, nil, err
	}
	return s.statDao.Search(req, pa)
}

// QueryStatData 查询指定统计数据点位
func (s *TelemetryService) QueryStatData(req *dto.QueryMetricStatDto) (*models.MetricStatValueData, error) {
	return s.statDao.Query(req)
}

// QueryStatSumData 查询指定统计数据求和值
func (s *TelemetryService) QueryStatSumData(req *dto.SearchMetricStatDto) (*models.MetricValueData, error) {
	return s.statDao.QuerySum(req)
}

func (s *TelemetryService) WriteData(data ...*models.MetricData) (int64, error) {
	a1, err := s.dataDao.BatchAdd(data...)
	if err != nil {
		return a1, err
	}
	a2, err := s.latestDao.BatchAdd(data...)
	if err != nil {
		return a1, err
	}
	return a1 + a2, nil
} //写入多个测点（覆盖）

func (s *TelemetryService) WriteStat(data []*models.MetricStatData, merge bool) (int64, error) {
	if merge {
		return s.statDao.MergeAdd(data...)
	}
	return s.statDao.CoverAdd(data...)
}

// NameByKeys 指定name名称
func (s *TelemetryService) NameByKeys(keys ...string) string {
	if len(keys) == 0 {
		return ""
	}
	ks := []string{}
	for _, v := range keys {
		if v == "" {
			continue
		}
		ks = append(ks, v)
	}

	return fmt.Sprintf("CUS_%s", strings.Join(ks, "."))
}
